package com.ynet.middleground.mobile.approve.utils;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiGetJsapiTicketResponse;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.google.common.base.Throwables;
import com.taobao.api.ApiException;
import com.ynet.cache.redis.IfpRedisson;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.mobile.approve.conf.AppConfig;
import com.ynet.middleground.mobile.approve.constant.UrlConstant;
import com.ynet.middleground.mobile.approve.response.OperateRecord;

/**
 * 获取access_token 和 jsTicket方法
 *
 * @author liulx
 * @date 2020-11-26
 */
@Service
public class ApiHelper {

    /**
     * 钉钉 token 缓存于 Redis 中的 key
     */
    private static final String REDIS_ACCESS_TOKEN_KEY = "ifp:dingtalk:accesstoken";

    /**
     * 钉钉 jsticket 缓存于 Redis 中的 key
     */
    private static final String REDIS_JSTICKET_KEY = "ifp:dingtalk:jsticket";

    /**
     * 缓存时间：1 小时 50 分钟
     */
    private static final long CACHE_TTL = 60 * 110;

    private AppConfig appConfig;

    @Autowired
    private IfpRedisson ifpRedisson;

    @Autowired
    public ApiHelper(AppConfig appConfig) {
        this.appConfig = appConfig;
    }

    /**
     * 在此方法中，为了避免频繁获取 access_token， <br>
     * 在距离上一次获取 access_token 时间在两个小时之内的情况，<br>
     * 将直接从持久化存储中读取 access_token
     *
     * 因为 access_token 和 jsapi_ticket 的过期时间都是 7200 秒,所以在获取 access_token 的同时也去获取了 jsapi_ticket <br>
     * 注：jsapi_ticket 是在前端页面 JSAPI 做权限验证配置的时候需要使用的 具体信息请查看开发者文档 -- 权限验证配置
     *
     * @return accessToken
     */
    public String getAccessToken() {
        // 从 Redis 中读取
        String accessToken = ifpRedisson.get(REDIS_ACCESS_TOKEN_KEY);
        if (accessToken != null) {
            return accessToken;
        }

        DefaultDingTalkClient client = new DefaultDingTalkClient(UrlConstant.URL_GET_TOKEN);
        OapiGettokenRequest request = new OapiGettokenRequest();
        OapiGettokenResponse response;

        request.setAppkey(appConfig.getAppKey());
        request.setAppsecret(appConfig.getAppSecret());
        request.setHttpMethod("GET");

        try {
            response = client.execute(request);
        } catch (ApiException e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(),
                "getAccessToken failed, case: {}", Throwables.getStackTraceAsString(e));
            throw new BusinessException(e.getErrMsg(), e.getErrCode());
        }

        accessToken = response.getAccessToken();

        ifpRedisson.set(REDIS_ACCESS_TOKEN_KEY, accessToken, CACHE_TTL);
        return accessToken;
    }

    /**
     * 获取 JSTicket, 用于 js 的签名计算 <br>
     *
     * @return jsTicket
     */
    public String getJsTicket() {
        // 从 Redis 中读取
        String ticket = ifpRedisson.get(REDIS_JSTICKET_KEY);
        if (ticket != null) {
            return ticket;
        }

        String accessToken = getAccessToken();

        DefaultDingTalkClient client = new DefaultDingTalkClient(UrlConstant.URL_GET_JSTICKET);
        OapiGetJsapiTicketRequest request = new OapiGetJsapiTicketRequest();
        OapiGetJsapiTicketResponse response;

        request.setHttpMethod("GET");

        try {
            response = client.execute(request, accessToken);
        } catch (ApiException e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(),
                "getJsapiTicket failed, case: {}", Throwables.getStackTraceAsString(e));
            throw new BusinessException(e.getErrMsg(), e.getErrCode());
        }

        if (!response.isSuccess()) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(),
                "getJsapiTicket failed, case: {}", response);
            throw new BusinessException(response.getErrmsg(), response.getErrorCode());
        }
        ticket = response.getTicket();
        ifpRedisson.set(REDIS_JSTICKET_KEY, ticket, CACHE_TTL);
        return ticket;
    }

    public static void main(String[] args) {
        List<OperateRecord> businessOperateList = new ArrayList<>();
        String a =
            "[{\"operate\":0,\"data\":[{\"name\":\"租赁合同\",\"value\":\"租赁.txt\"},{\"name\":\"劳动合同\",\"value\":\"劳动.txt\"}]},{\"operate\":0,\"data\":[{\"name\":\"租赁合同\",\"value\":\"租赁.txt\"},{\"name\":\"劳动合同\",\"value\":\"劳动.txt\"}]}]";

        JSONArray jsonArray = JSON.parseArray(a);
        for (Object o : jsonArray) {
            JSONObject jsonObject = (JSONObject)o;
            OperateRecord business = JSONObject.toJavaObject(jsonObject, OperateRecord.class);
            businessOperateList.add(business);
        }
        System.out.println(businessOperateList.toString());

    }
}
